/*
 * main.c
 *
 * Group: Fantastic Five
 * Date: 4/25/08
 *
 * Description: Program to read in a file containing a program, tokenize, parse, and run it
 */

#include <stdlib.h>
#include <stdio.h>
#include "lexer.h"
#include "parser.h"
#include "vm.h"
#define MAX_LINE 10000

void empty_exit(int, struct token_list *, struct instr_list *);

int main(int argc, char *argv[])
{
    if(argc == 2)
    {
        /* open program file */
        FILE *prog = fopen(argv[1], "r");
        
        /* Check if file is valid */
        if(prog == NULL)
        {
            fprintf(stderr, "Please enter a valid file.\n");
            exit(1);
        }

        char line[MAX_LINE];
        char delims[] = " \t\n,";
        struct token_list *tl = new_token_list();
        struct instr_list *il = new_instr_list();
        int linenum = 0;
        int num_errors = 0;

        /* Loop until EOF */
        while((fgets(line, MAX_LINE, prog)) != NULL)
        {
            /* Increment line number */
            ++linenum;
            /* Run lexer on line */
            num_errors += lex(stdout, stderr, line, linenum, delims, tl);
        }

        /* close file */
        fclose(prog);

        if(num_errors != 0) /* if errors found in tokenizing, exit */
        {
            fprintf(stderr, "%i errors found in tokenizing program, exiting...\n", num_errors);
            empty_exit(1, tl, il);
        }

        /* parse error free token list */
        num_errors += parse(stdout, stderr, tl, il);

        if(num_errors != 0) /* if errors found in parsing, exit */
        {
            fprintf(stderr, "%i errors found in parsing program, exiting...\n", num_errors);
            empty_exit(2, tl, il);
        }

        /* run program in vm */
        vm_run_program(stdout, stdin, stderr, il);
        empty_exit(0, tl, il);
    }
    else
    {
        fprintf(stderr, "Please run with a program as a command line argument.  ./main program.asm\n");
    }
}

/* empty lists and free memory used by them */
void empty_exit(int code, struct token_list *tl, struct instr_list *il)
{
    empty_token_list(tl);
    free(tl);
    tl = NULL;
    empty_instr_list(il);
    free(il);
    il = NULL;

    exit(code);
}

